package com.zbkj.crmeb.payment.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.zbkj.crmeb.chant.model.ChannelMerchantAccount;
import com.zbkj.crmeb.chant.service.IChannelMerchantAccountService;
import com.zbkj.crmeb.enums.AccountFlowTypeEnum;
import com.zbkj.crmeb.enums.OrderTradeTypeEnum;
import com.zbkj.crmeb.finance.model.UserRecharge;
import com.zbkj.crmeb.finance.service.UserRechargeService;
import com.zbkj.crmeb.payment.service.OrderPayService;
import com.zbkj.crmeb.payment.service.PayService;
import com.zbkj.crmeb.payment.service.RechargePayService;
import com.zbkj.crmeb.payment.vo.wechat.AttachVo;
import com.zbkj.crmeb.payment.vo.wechat.CreateOrderResponseVo;
import com.zbkj.crmeb.payment.vo.wechat.PayParamsVo;
import com.zbkj.crmeb.payment.wechat.WeChatPayService;
import com.zbkj.crmeb.sms.service.SmsService;
import com.zbkj.crmeb.store.model.StoreAccountInfo;
import com.zbkj.crmeb.store.service.AccountFlowService;
import com.zbkj.crmeb.store.service.StoreAccountInfoService;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.request.UserOperateFundsRequest;
import com.zbkj.crmeb.user.service.UserService;
import com.zbkj.crmeb.wechat.service.TemplateMessageService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Objects;


/**
 * <p>
 * 支付类
 * </p>
 *
 * @author Mr.Zhang
 * @since 2020-04-10
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Service
public class RechargePayServiceImpl extends PayService implements RechargePayService {
    private static final Logger logger = LoggerFactory.getLogger(OrderPayServiceImpl.class);

    @Autowired
    private UserRechargeService userRechargeService;

    @Lazy
    @Autowired
    private WeChatPayService weChatPayService;

    @Autowired
    private UserService userService;

    @Autowired
    private TemplateMessageService templateMessageService;

    @Autowired
    private SmsService smsService;

    //订单类
    private UserRecharge userRecharge;

    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private StoreAccountInfoService storeAccountInfoService;
    @Autowired
    private IChannelMerchantAccountService channelMerchantAccountService;
    @Autowired
    private AccountFlowService accountFlowService;

    /**
     * 订单支付
     * @param orderId Integer 订单号
     * @param payType String 支付类型
     * @author Mr.Zhang
     * @since 2020-06-22
     * @return PayResponseVo
     */
    @Override
    public CreateOrderResponseVo payOrder(Integer orderId, String payType, String clientIp) {

        try{
        	UserRecharge userRecharge = userRechargeService.getById(orderId);
            setUserRecharge(userRecharge);
            //针对order进行验证, 是否未支付验证
            beforePay();

            //支付需要的参数
            PayParamsVo payParamsVo = new PayParamsVo(
                    getUserRecharge().getOrderId(),
                    getUserRecharge().getRechargeType(),
                    clientIp,
                    getProductName(),
                    getUserRecharge().getPrice(),
                    getUserRecharge().getUid(),
                    new AttachVo(Constants.SERVICE_PAY_TYPE_RECHARGE, getUserRecharge().getUid())
            );

            switch (payType){
                case Constants.PAY_TYPE_WE_CHAT: // 微信支付
                case Constants.PAY_TYPE_WE_CHAT_NATIVE: // 微信扫码支付
                	payParamsVo.setMerId(userRecharge.getMerId());
                    return weChatPayService.create(payParamsVo);//构造下单类
                //TODO 其他支付方式
                default:
                    throw new CrmebException("未识别当前支付方式！");
            }
        }catch (Exception e){
            throw new CrmebException(e.getMessage());
        }
    }

    /**
     * 支付之前
     * @author Mr.Zhang
     * @since 2020-06-22
     */
    private void beforePay() {
        checkOrderUnPay();
    }


    /**
     * 充值支付成功
     * @param orderId String 订单号
     * @param userId Integer 用户id
     * @param payType String 支付类型
     * @author Mr.Zhang
     * @since 2020-06-22
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public boolean success(String orderId, Integer userId, String payType, String outOrderId, String backParam) {
        try{
            UserRecharge userRecharge = new UserRecharge();
            userRecharge.setOrderId(orderId);
//            userRecharge.setUid(userId);
            userRecharge = userRechargeService.getInfoByEntity(userRecharge);
            setUserRecharge(userRecharge);

            //充值支付之前
            beforePay();
            //余额变动
            userOperateFunds(userRecharge);
            // 商户资金操作
            ChannelMerchantAccount channelMerchantAccount = new ChannelMerchantAccount();
            channelMerchantAccount.setMerId(userRecharge.getMerId());
            boolean isOrange = Objects.equals(userRecharge.getPayments(), Constants.PAY_TYPE_ORAGE_PAY);
            channelMerchantAccount.setAccount(isOrange ? userRecharge.getPrice() : null)
                    .setWithdrawAccount(isOrange ? null : userRecharge.getPrice());
            channelMerchantAccountService.calcMoney(channelMerchantAccount);
            // 流水操作
            accountFlowService.saveAccountFlow(userRecharge.getMerId(), userRecharge.getId(), null, null, AccountFlowTypeEnum.RECHARGE,
                    isOrange ? userRecharge.getPrice() : null,
                    isOrange ? null : userRecharge.getPrice(), null, "用户充值");
            //更新订单支付状态
            Boolean complete = userRechargeService.complete(getUserRecharge());
            if(!complete){
                throw new CrmebException("订单更新失败");
            }

            //充值支付成功之后, 需要事物处理
            //afterPaySuccess(getUserRecharge());

            //新增账户明细表
            User user = userService.getById(userRecharge.getUid());
            StoreAccountInfo info = new StoreAccountInfo();
            info.setOutOrderId(outOrderId);
            info.setOrderId(userRecharge.getOrderId());
            info.setUid(userRecharge.getUid());
            if(null!= user){
                info.setRealName(user.getNickname());
                info.setNowMoney(user.getNowMoney());
            }
            info.setTradeType(OrderTradeTypeEnum.RECHARGE.getType());
            info.setTradePrice(userRecharge.getPrice());
            info.setPayType(payType);
            info.setRemark("微信充值" + userRecharge.getPrice());
            storeAccountInfoService.save(info);
            return true;
        }catch (Exception e){
            throw new CrmebException("订单支付回调失败，" + e.getMessage());
        }
    }

    private void merOperateFunds(UserRecharge recharge) {
        // 资金操作
        ChannelMerchantAccount channelMerchantAccount = new ChannelMerchantAccount();
        channelMerchantAccount.setMerId(recharge.getMerId());
        channelMerchantAccount.setAccount(recharge.getPrice());
        channelMerchantAccountService.calcMoney(channelMerchantAccount);
        // 订单记录操作
        UserRecharge userRecharge = new UserRecharge();
        userRecharge.setMerId(recharge.getMerId());
        userRecharge.setOrderId(recharge.getOrderId());
        userRecharge.setPrice(recharge.getPrice());
        userRecharge.setType(false);
        userRecharge.setStatus(1);
        userRecharge.setRechargeType(Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM);
        userRecharge.setPaid(true);
        userRecharge.setCreateTime(new Date());
        userRecharge.setUpdateTime(new Date());
        userRechargeService.save(userRecharge);
        // 流水操作
        accountFlowService.saveAccountFlow(userRecharge.getMerId(), userRecharge.getId(), null, null, AccountFlowTypeEnum.RECHARGE, userRecharge.getPrice(), null, null, "用户充值");
    }

    /**
     * 充值支付成功之后, 需要事物处理
     * @author Mr.Zhang
     * @since 2020-06-22
     */
    private void afterPaySuccess(UserRecharge userRecharge) {
        try {
            //增加经验、积分
            updateUserFounds(userRecharge);

            //下发模板通知
            pushTempMessage(userRecharge);

        }catch (Exception e){
            throw new CrmebException(e.getMessage());
        }
    }

    /**
     * 充值支付 - 余额变动
     */
    private void userOperateFunds(UserRecharge userRecharge) {
        UserOperateFundsRequest userOperateFundsRequest = new UserOperateFundsRequest();
        userOperateFundsRequest.setValue(userRecharge.getPrice().add(userRecharge.getGivePrice()));
        userOperateFundsRequest.setFoundsType(Constants.USER_BILL_TYPE_PAY_RECHARGE);
        userOperateFundsRequest.setUid(userRecharge.getUid());
        userOperateFundsRequest.setTitle("充值支付");
        userOperateFundsRequest.setFoundsCategory(Constants.USER_BILL_CATEGORY_MONEY);
        userOperateFundsRequest.setType(1);
        boolean result = userService.updateFounds(userOperateFundsRequest, false);
        if(!result){
            throw new CrmebException("用户余额更新失败");
        }
    }

    /**
     * 充值支付成功之后 - 增加经验、积分
     * @param userRecharge
     */
    private void updateUserFounds(UserRecharge userRecharge) {
        userService.consumeAfterUpdateUserFounds(userRecharge.getUid(), userRecharge.getId().toString(), userRecharge.getPrice(), Constants.USER_BILL_TYPE_PAY_RECHARGE);
    }

    /**
     * 充值支付成功之后 - 发送模板消息通知
     * @author Mr.Zhang
     * @since 2020-07-01
     */
    private void pushTempMessage(UserRecharge userRecharge) {
        User info = userService.getById(userRecharge.getUid());

        String tempKey = Constants.WE_CHAT_PUBLIC_TEMP_KEY_RECHARGE;
        if(Constants.PAY_TYPE_WE_CHAT_FROM_PROGRAM.equals(userRecharge.getRechargeType())){
            tempKey = Constants.WE_CHAT_PROGRAM_TEMP_KEY_RECHARGE;
        }

        HashMap<String, String> map = new HashMap<>();
        map.put("rechargeOrderId", userRecharge.getOrderId());
        map.put("rechargeAmount", userRecharge.getPrice().add(userRecharge.getGivePrice()).toString());
        map.put("rechargeAfterBalance", info.getNowMoney().toString());
        map.put("rechargeDate", userRecharge.getOrderId());

        templateMessageService.push(tempKey, map, userRecharge.getUid(), userRecharge.getRechargeType());
    }

    /**
     * 检测是否未支付
     * @author Mr.Zhang
     * @since 2020-06-22
     */
    private void checkOrderUnPay() {
        if(null == getUserRecharge()){
            throw new CrmebException("没有找到订单信息");
        }

        if(getUserRecharge().getPaid()){
            throw new CrmebException("当前操作被禁止，订单已经被处理");
        }
    }

    /**
     * 获取订单产品名称
     * @author Mr.Zhang
     * @since 2020-06-22
     * @return String
     */
    private String getProductName(){

        return "余额充值" + getUserRecharge().getPrice() + "元!";
    }
}
